package com.meilian.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilian.clients.*;
import com.meilian.param.ProductHotParam;
import com.meilian.param.ProductIdsParam;
import com.meilian.param.ProductSaveParam;
import com.meilian.param.ProductSearchParam;
import com.meilian.pojo.Picture;
import com.meilian.pojo.Product;
import com.meilian.product.mapper.PictureMapper;
import com.meilian.product.mapper.ProductMapper;
import com.meilian.product.service.ProductService;
import com.meilian.to.OrderToProduct;
import com.meilian.utils.R;
import lombok.extern.flogger.Flogger;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

//产品实现类
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper,Product> implements ProductService {

    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private PictureMapper pictureMapper;
    @Autowired
    private SearchClient searchClient;

    @Autowired
    private CollectClient collectClient;
    @Autowired
    private CartClient cartClient;
    @Autowired
    private OrderClient orderClient;

    /**
     * 单类别名称 查热门商品,至多7条数据
     * 1.根据类别名称,调用 feign客户端访问类别服务获取类别的数据
     * 2.成功 继续根据类别id查询商品数据[热门 销售量,查询7条]
     * 3.封装结果
     * @param categoryName
     * cacheManagerHour 配置类的方法 默认缓存时间为1小时
     * 第三个参数可留可不留
     * cacheManagerDay  缓存时间为一天
     * @return
     */
    @Cacheable(value = "list.product",key = "#categoryName",cacheManager = "cacheManagerHour")
    @Override
    public R promo(String categoryName) {
        R r = categoryClient.byName(categoryName);
        if (r.getCode().equals(R.FAIL_CODE)) {
            log.info("ProductserviceImpl.promo业务结束，结果:{}","类别查询失败!");

            return r;
        }
        //类别服务中 data = category --- feign {json}  ----- product服务 LinkedHashMap jackson

        LinkedHashMap<String,Object>map= (LinkedHashMap<String, Object>) r.getData();
        Integer categoryId = (Integer) map.get("category_id");
        //封装查询参数
        QueryWrapper<Product> productQueryWrapper=new QueryWrapper<>();
        productQueryWrapper.eq("category_id",categoryId);
        productQueryWrapper.orderByDesc("product_sales");
        IPage<Product> page=new Page<>(1,7);

        page=productMapper.selectPage(page,productQueryWrapper);
        List<Product> productList=page.getRecords();//获取指定也的数据
        long total=page.getTotal();//获取总条数

        log.info("ProductServiceImpl.promo业务结束，结果:{}" , productList);

        return R.ok("数据查询成功",productList);
    }

    /**
     * 多类别热门商品查询 根据类别名称集合! 查7条
     * 1.调用类别服务
     * 2.类别集合id查询商品
     * 3.封装结果集
     * @param productHotParam  类别名称集合
     * @return R
     * cacheManager = "cacheManagerHour" 不写也是缓存1小时
     */
    @Cacheable(value = "list.product",key = "#productHotParam.categoryName")
    @Override
    public R hots(ProductHotParam productHotParam) {
        R r = categoryClient.hots(productHotParam);
        if (r.getCode().equals(R.FAIL_CODE)) {
            log.info("ProductServiceImpl. hots业务结束，结果:{}",r.getMsg());
            return r;
        }
        List<Object> ids= (List<Object>) r.getData();//获取商品类别id集合

        //查询商品数据
        QueryWrapper<Product> productQueryWrapper=new QueryWrapper<>();
        productQueryWrapper.in("category_id",ids);
        productQueryWrapper.orderByDesc("product_sales");

        IPage<Product> page=new Page<>(1,7);

        page = productMapper.selectPage(page, productQueryWrapper);

        List<Product> records=page.getRecords();
        R ok=R.ok("多类别热门商品查询成功!",records);
        log.info("ProductServiceImpl.hots业务结束,结果:{}",ok);
        return ok;
    }

    /**
     * 查询类别商品集合
     * @return
     */
    @Override
    public R clist() {
        R r  = categoryClient.list();
        log.info( "ProductServiceImpl.clist业务结束，结果:{}",r);
        return r;
    }

    /**
     * 通用性业务
     * 传入了id ,根据id查询 并分页
     * 没有传入类别的id,就查询全部
     * @param productIdsParam
     * @return
     */
    @Override
    @Cacheable(value = "list.product",key = "#productIdsParam.categoryID+'-'+#productIdsParam.currentPage+'-'+#productIdsParam.pageSize")
    public R byCategory(ProductIdsParam productIdsParam) {

        List<Integer> categoryID = productIdsParam.getCategoryID();

        QueryWrapper<Product> productQueryWrapper=new QueryWrapper<>();
        if (!categoryID.isEmpty()) {
            productQueryWrapper.in("category_id",categoryID);
        }

        IPage<Product> page=new Page<>(productIdsParam.getCurrentPage(),productIdsParam.getPageSize());

        page = productMapper.selectPage(page, productQueryWrapper);
        //结果集封装
        R ok = R.ok("查询成功!", page.getRecords(), page.getTotal());

        log.info("ProductServiceImpl.byCategory业务结束,结果:{}",ok);

        return ok;
    }

    /**
     * 根据商品Id,查询商品详情信息
     * @param productID
     * @return
     */
    @Cacheable(value = "product",key = "#productID")
    @Override
    public R detail(Integer productID) {
        Product product = productMapper.selectById(productID);
        R ok = R.ok(product);
        log.info( "ProductServiceImpl.detail业务结束，结果:{}",ok);

        return ok;
    }


    /**
     * 查询商品对应图片详情的集合
     * @param productID
     * @return
     */
    @Cacheable(value = "picture",key = "#productID")
    @Override
    public R pictures(Integer productID) {

        QueryWrapper<Picture> pictureQueryWrapper=new QueryWrapper<>();

        pictureQueryWrapper.eq("product_id",productID);

        List<Picture> pictureList = pictureMapper.selectList(pictureQueryWrapper);

        R ok = R.ok(pictureList);

        log.info("ProductServiceImpl.pictures业务结束，结果:{}" , ok);

        return ok;
    }

    /**
     * cacheManagerDay 指缓存一天
     * #root.methodName 指方法名
     * 搜索服务调用,获取全部商品数据
     * 进行同步
     * 返回 商品数据集合
     */
    //@Cacheable(value = "list.category",key = "#root.methodName",cacheManger="cacheManagerDay")

    @Override
    public List<Product> allList() {
        List<Product> productList = productMapper.selectList(null);

        log.info("ProductServiceImpl.allList业务结束, 结果:{}", productList.size());
        return productList;
    }
    @Cacheable(value = "list.product",key = "#productParamsSearch.search+'-'+#productParamsSearch.pageSize+'-'+#productParamsSearch.currentPage")
    @Override
    public R search(ProductSearchParam productSearchParam) {

        R r = searchClient.search(productSearchParam);
        log.info("ProductServiceImpl.search业务结束，结果:{}",r);
        return r;
    }


    /**
     * 根据商品id集合查询商品信息
     * @param productIds
     * @return
     */
    @Cacheable(value = "list.product",key = "#productIds")
    @Override
    public R ids(List<Integer> productIds) {

        QueryWrapper<Product> queryWrapper=new QueryWrapper<>();
        queryWrapper.in("product_id",productIds);

        //获取已收藏的商品id查询相关信息
        List<Product> productList = productMapper.selectList(queryWrapper);

        R r = R.ok("类别信息查询成功!", productList);
        log.info("ProductServiceImpl.ids业务结束,结果:{}",r);
        return r;
    }

    @Override
    public List<Product> cartList(List<Integer> productIds) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_id",productIds);

        List<Product> productList = productMapper.selectList(queryWrapper);
        log.info("ProductCartController.cartList业务结束,结果:{}", productList);
        return productList;
    }


    /**
     * 修改库存和增加销售量
     * @param orderToProducts
     */
    @Override
    public void subNumber(List<OrderToProduct> orderToProducts) {
        //将集合转成map  productId  orderToProduct
        Map<Integer,OrderToProduct> map= orderToProducts.stream().collect(Collectors.toMap(OrderToProduct::getProductId,v->v));
        //获取商品id集合
        Set<Integer> productIds = map.keySet();
        //查询商品集合对应的商品信息
        List<Product> productList = productMapper.selectBatchIds(productIds);
        //修改商品信息
        for (Product product:productList){
            //获取商品的库存 productNum
            Integer num = map.get(product.getProductId()).getNum();
            product.setProductNum(product.getProductNum()-num);//最新的库存 = 原有的商品库存 减去 订单的数量
            product.setProductSales(product.getProductSales()+num);//增加销售量
        }

        //批量更新
        this.updateBatchById(productList);
        log.info("ProductServiceImpl.subNumber业务结束，结果:库存和销售量的修改完毕");

    }

    /**
     * 类别对应的商品数量查询
     * @param categoryId
     * @return
     */
    @Override
    public Long adminCount(Integer categoryId) {

        QueryWrapper<Product> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("category_id",categoryId);
        Long count = baseMapper.selectCount(queryWrapper);
        log.info("ProductServiceImpl.adminCount业务结束，结果:{}",count);

        return count;
    }

    /**
     * 添加保存商品业务
     * 1.保存商品数据
     * 2.商品图片详情切割和保存
     * 3.搜索数据的数据添加
     * 4.清空商品相关的缓存数据
     * @param productSaveParam
     * @return
     */
    @CacheEvict(value = "list.product",allEntries = true)
    @Override
    public R adminSave(ProductSaveParam productSaveParam) {
        Product product=new Product();
        BeanUtils.copyProperties(productSaveParam,product);
        int rows=productMapper.insert(product);//插入商品数据
        log.info( "ProductServiceImpl.adminsave业务结束，结果:{}" , rows);
        //商品图片获取 +
        String pictures = productSaveParam.getPictures();
        if (!StringUtils.isEmpty(pictures)) {
            //截取特殊字符串的时候 可在前面加 \\ 或用[]包住--> $ ,+,#,?
            String[] urls = pictures.split("\\+");
            for (String url :urls){
                Picture picture=new Picture();
                picture.setProductId(product.getProductId());
                picture.setProductPicture(url);
                pictureMapper.insert(picture);//插入商品图片
            }
        }

        //同步搜索服务的数据
        searchClient.saveOrUpdate(product);

        return R.ok("商品数据添加成功!");
    }

    /**
     * 后台商品数据更新
     * 1.更新商品数据
     * 2.同步搜索服务数据
     * @param product
     * @return
     */
    @Override
    public R adminUpdate(Product product) {
        productMapper.updateById(product);
        searchClient.saveOrUpdate(product);
        return R.ok("商品数据更新成功!");
    }

    /**
     * 商品删除业务
     * 1.检查购物车
     * 2.检查订单
     * 3.删除商品
     * 4.删除商品相关图片
     * 5.删除收藏
     * 6.同步es库数据
     * 7.清空缓存
     * @param productId
     * @return
     */
    @Caching(
            evict = {
                    @CacheEvict(value = "list.product",allEntries = true),
                    @CacheEvict(value = "product",allEntries = true,key = "#productId")
            }
    )
    @Override
    public R adminRemove(Integer productId) {

        R r = cartClient.check(productId);
        if ("004".equals(r.getCode())) {
            log.info( "ProductServiceImpl.adminRemove业务结束，结果:{}" , r.getMsg());
            return r;
        }
        r = orderClient.check(productId);
        if ("004".equals(r.getCode())) {
            log.info( "ProductServiceImpl.adminRemove业务结束，结果:{}" , r.getMsg());
            return r;
        }

        //删除商品
        productMapper.deleteById(productId);
        //删除商品图片
        QueryWrapper<Picture> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("product_id",productId);
        pictureMapper.delete(queryWrapper);

        //删除删除中和本商品有关的数据
        collectClient.remove(productId);

        //同步数据
        searchClient.remove(productId);
        return R.ok("商品删除成功!");
    }
}
